﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using Windows.UI.Xaml;
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;
using CC98.Data;
using CC98.Metro.Common;

namespace CC98.Metro
{
    public static class CommandHandler
    {
        public static readonly EventCommand SwitchUser = new EventCommand();

        public static readonly EventCommand Navigate = new EventCommand();

        public static readonly EventCommand ClearNavigationHistory = new EventCommand();

        static CommandHandler()
        {
            // Hook
            SwitchUser.Executing += SwitchUser_Executing;
            Navigate.Executing += Navigate_Executing;
            ClearNavigationHistory.Executing += ClearNavigationHistory_Executing;
            // Build dict
            foreach(var field in typeof(CommandHandler).GetRuntimeFields())
            {
                if(!field.Name.StartsWith("_"))
                    _cmdDict[field.Name] = (EventCommand)field.GetValue(null);
            }
        }

        public static void Initialize(Frame mainFrame)
        {
            MainFrame = mainFrame;
            originalNavigationState = MainFrame.GetNavigationState();
        }

        private static Frame MainFrame { get; set; }

        #region methods

        public static void NavigateTo(Type type, object parameter)
        {
            Navigate_Executing(null, new ExecutingEventArgs(new NavigationCommandParameter()
            {
                Type = type, 
                Parameter = parameter
            }));
        }

        #endregion

        private static void Navigate_Executing(object sender, ExecutingEventArgs e)
        {
            _currentWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
                {
                    var navParam = (NavigationCommandParameter)e.Parameter;
                    MainFrame.Navigate(navParam.Type, navParam.Parameter);
                }));
        }

        public static void Execute(string name, object parameter)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("Invalid name");
            EventCommand command = null;
            if (_cmdDict.TryGetValue(name, out command))
                command.Execute(parameter);
            else
                throw new ArgumentException("Cannot find command:" + name);
        }

        private static void SwitchUser_Executing(object sender, ExecutingEventArgs e)
        {
            var user = (User)e.Parameter;
            // TODO: Switch user
        }

        private static void ClearNavigationHistory_Executing(object sender, ExecutingEventArgs e)
        {
            _currentWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
                {
                    MainFrame.SetNavigationState(originalNavigationState);
                }));
        }

        private static readonly Dictionary<string, EventCommand> _cmdDict = new Dictionary<string, EventCommand>();

        private static readonly Window _currentWindow = Window.Current;

        private static string originalNavigationState;
    }

    public struct NavigationCommandParameter
    {
        public Type Type { get; set; }

        public object Parameter { get; set; }
    }
}
